/**
* jsgig.vi - JSGIG virtual input.
* 
* Depends: jsgig.event
* 
* The virtual input module defines a class, VirtualInputDevice, which can be 
* used to simulate a user input device such as a control pad or stick
* programmatically. Note that it can NOT process input from actual, physical
* joysticks or gamepads because this is beyond the capabilities of standard
* web browsers.
* 
* This module currently does not need to be initialized after inclusion.
*/
if (!jsgig) {
  throw new Error("jsgig/jsgig.js must be included before jsgig/vi.js");
}
if (!jsgig.event) {
  throw new Error("jsgig/event.js must be included before jsgig/vi.js");
}
if (!jsgig.vi) { jsgig.vi = (function() {
var my = {};

var _init = false;
var _lastIDN = -1;
var KEYS = jsgig.KEYS;

/**
* Create a default VID using the next available IDN.
* 
*  var vid = jsgig.vi.createDefault();
* 
* The default VID has the following keymap:
* 
*  {
*   left: KEYS.left,
*   right: KEYS.right,
*   up: KEYS.up,
*   down: KEYS.down,
*   a: KEYS.z,
*   b: KEYS.x,
*   start: KEYS.enter,
*   select: KEYS.shift
*  }
*/
my.createDefault = function createDefault() {
  return new my.VirtualInputDevice({
    left: KEYS.left,
    right: KEYS.right,
    up: KEYS.up,
    down: KEYS.down,
    a: KEYS.z,
    b: KEYS.x,
    start: KEYS.enter,
    select: KEYS.shift
  });
}

/**
* Represents a virtual input device (VID) used to get data from the user.
* 
*  var myVID = new jsgig.vi.VirtualInputDevice(
*    {
*      input1name : input1key,
*      ...
*      inputNname : inputNkey
*    }
*    [, id]
*  );
*     
* Each VID created will be assigned to the jsgig.vi module as an attribute with
* a name that is equal to the value of the given ID. If no ID is given, a
* sequential number will be used. The first VID created, therefore, can be
* accessed as jsgig.vi[0], the second can be accessed as jsgig.vi[1], and so on.
* 
* When a VID is no longer needed, you must call the `.destroy()` method on it.
* This ensures that all event listeners that the VID was using are removed, and
* that the VID is removed from the module's attributes.
*/
my.VirtualInputDevice = util.extend(
  Object,
  
  function VirtualInputDevice(keymap, id) {
    this.id = id = (id === undefined ? ++_lastIDN : id);
    
    var v2k = this._viToKey = {};
    var k2v = this._keyToVi = {};
    for (var vi in keymap) {
      var key = keymap[vi];
      v2k[vi] = key;
      k2v[key] = vi;
      this[vi] = false;
    }
    $(window).on({keydown: this._onKeydown, keyup: this._onKeyup}, this);
    my[id] = this;
  },
  
  function _onKeydown (e) {
    var k2v = e.data._keyToVi;
    var key = e.keyCode;
    if (key in k2v) {
      e.data[k2v[key]] = true;
      var subE = $.Event("vidown");
      subE.target = e.data;
      subE.vi = k2v[key];
      $(window).trigger(subE);
    }    
  },
  
  function _onKeyup (e) {
    var k2v = e.data._keyToVi;
    var key = e.keyCode;
    if (key in k2v) {
      e.data[k2v[key]] = false;
      var subE = $.Event("viup");
      subE.target = e.data;
      subE.vi = k2v[key];
      $(window).trigger(subE);
    }
  },
  
  function destroy(e) {
    $(window).off({keydown: this._onKeydown, keyup: this._onKeyup});
    delete my[this.id];
  },
  
  function anyOf() {
    for (var i in arguments) {
      if (this[arguments[i]])
        return true;
    }
    return false;
  },
  
  function allOf() {
    for (var i in arguments) {
      if (!this[arguments[i]])
        return false;
    }
    return true;
  },
  
  function noneOf() {
    for (var i in arguments) {
      if (this[arguments[i]])
        return false;
    }
    return true;
  }
);

// End of module `jsgig.vi`
return my; })();}